package com.atxiaodei.kabudasockerserverdemo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @ClassName NewIoServer
 * @Deacription TODO
 * @Author 卡布达
 * @Date 2021/10/27 16:32
 * @Version 1.0
 **/
public class NewIoServer {
    static Selector selector;
    public static void main(String[] args) {
        try {
            selector=Selector.open();
            // selector 必须是非阻塞的
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(8080));
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 把连接事件注册到多路复用器上
            while (true){
                selector.select();// 阻塞机制
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()){
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    if (key.isAcceptable()) {// 连接事件
                        handleAccept(key);
                    }else if(key.isReadable()){// 读的就绪事件
                        //
                        handleRead(key);
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void handleAccept(SelectionKey key) {
        ServerSocketChannel channel =(ServerSocketChannel) key.channel();
        try {
            SocketChannel socketChannel = channel.accept();// 建立一个连接
            socketChannel.configureBlocking(false);
            socketChannel.write(ByteBuffer.wrap("客户端你好，我是NIO服务端".getBytes()));
            socketChannel.register(selector,SelectionKey.OP_READ);// 注册读事件

        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    // 接收客户端消息
    private static void handleRead(SelectionKey key) {
        SocketChannel socketChannel=(SocketChannel)key.channel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        try {
            socketChannel.read(byteBuffer);

            String msg = new String(byteBuffer.array());
            System.out.println("服务端接收到消息"+msg);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
